<!DOCTYPE html>



  


<html class="theme-next pisces use-motion" lang="">
<head>
  <meta charset="UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>
<meta name="theme-color" content="#222">









<meta http-equiv="Cache-Control" content="no-transform" />
<meta http-equiv="Cache-Control" content="no-siteapp" />
















  
  
  <link href="/blog/lib/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css" />







<link href="/blog/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css" />

<link href="/blog/css/main.css?v=5.1.4" rel="stylesheet" type="text/css" />


  <link rel="apple-touch-icon" sizes="180x180" href="/blog/images/apple-touch-icon-next.png?v=5.1.4">


  <link rel="icon" type="image/png" sizes="32x32" href="/blog/images/favicon-32x32-next.png?v=5.1.4">


  <link rel="icon" type="image/png" sizes="16x16" href="/blog/images/favicon-16x16-next.png?v=5.1.4">


  <link rel="mask-icon" href="/blog/images/logo.svg?v=5.1.4" color="#222">





  <meta name="keywords" content="Hexo, NexT" />










<meta name="description" content="####1. Lucene 官网 ######1). 概述Lucene是一款高性能的、可扩展的信息检索（IR）工具库。信息检索是指文档搜索、文档内信息搜索或者文档相关的元数据搜索等操作。Lucene工具包下载">
<meta name="keywords" content="Android、iOS、Web、React Native">
<meta property="og:type" content="article">
<meta property="og:title" content="分布式--Lucene-全文检索">
<meta property="og:url" content="http://yoursite.com/blog/2018/08/06/Distributed/分布式--Lucene-全文检索/index.html">
<meta property="og:site_name" content="凌浩雨_博客">
<meta property="og:description" content="####1. Lucene 官网 ######1). 概述Lucene是一款高性能的、可扩展的信息检索（IR）工具库。信息检索是指文档搜索、文档内信息搜索或者文档相关的元数据搜索等操作。Lucene工具包下载">
<meta property="og:locale" content="default">
<meta property="og:image" content="https://upload-images.jianshu.io/upload_images/3110861-affc14faa0cff776.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240">
<meta property="og:image" content="https://upload-images.jianshu.io/upload_images/3110861-40a5c018bcc2b685.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240">
<meta property="og:image" content="https://upload-images.jianshu.io/upload_images/3110861-7a31faf9b6ba9ccb.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240">
<meta property="og:image" content="https://upload-images.jianshu.io/upload_images/3110861-5151fba2715c4c67.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240">
<meta property="og:image" content="https://upload-images.jianshu.io/upload_images/3110861-5c44a19d532b9c7f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240">
<meta property="og:image" content="https://upload-images.jianshu.io/upload_images/3110861-7861af3a89460de4.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240">
<meta property="og:image" content="https://upload-images.jianshu.io/upload_images/3110861-4a979331ce0be062.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240">
<meta property="og:image" content="https://upload-images.jianshu.io/upload_images/3110861-b0b3fdd6c7b6d1ba.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240">
<meta property="og:image" content="https://upload-images.jianshu.io/upload_images/3110861-d31d1f7b1da8e908.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240">
<meta property="og:image" content="https://upload-images.jianshu.io/upload_images/3110861-29d4776cfd2b9fc1.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240">
<meta property="og:image" content="https://upload-images.jianshu.io/upload_images/3110861-23458cf9cec8b683.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240">
<meta property="og:updated_time" content="2018-08-06T11:06:46.083Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="分布式--Lucene-全文检索">
<meta name="twitter:description" content="####1. Lucene 官网 ######1). 概述Lucene是一款高性能的、可扩展的信息检索（IR）工具库。信息检索是指文档搜索、文档内信息搜索或者文档相关的元数据搜索等操作。Lucene工具包下载">
<meta name="twitter:image" content="https://upload-images.jianshu.io/upload_images/3110861-affc14faa0cff776.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240">



<script type="text/javascript" id="hexo.configurations">
  var NexT = window.NexT || {};
  var CONFIG = {
    root: '/blog/',
    scheme: 'Pisces',
    version: '5.1.4',
    sidebar: {"position":"left","display":"post","offset":12,"b2t":false,"scrollpercent":false,"onmobile":false},
    fancybox: true,
    tabs: true,
    motion: {"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},
    duoshuo: {
      userId: '0',
      author: 'Author'
    },
    algolia: {
      applicationID: '',
      apiKey: '',
      indexName: '',
      hits: {"per_page":10},
      labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
    }
  };
</script>



  <link rel="canonical" href="http://yoursite.com/blog/2018/08/06/Distributed/分布式--Lucene-全文检索/"/>





  <title>分布式--Lucene-全文检索 | 凌浩雨_博客</title>
  








</head>

<body itemscope itemtype="http://schema.org/WebPage" lang="default">

  
  
    
  

  <div class="container sidebar-position-left page-post-detail">
    <div class="headband"></div>

    <header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-wrapper">
  <div class="site-meta ">
    

    <div class="custom-logo-site-title">
      <a href="/blog/"  class="brand" rel="start">
        <span class="logo-line-before"><i></i></span>
        <span class="site-title">凌浩雨_博客</span>
        <span class="logo-line-after"><i></i></span>
      </a>
    </div>
      
        <p class="site-subtitle"></p>
      
  </div>

  <div class="site-nav-toggle">
    <button>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
    </button>
  </div>
</div>

<nav class="site-nav">
  

  
    <ul id="menu" class="menu">
      
        
        <li class="menu-item menu-item-home">
          <a href="/blog/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-home"></i> <br />
            
            Home
          </a>
        </li>
      
        
        <li class="menu-item menu-item-archives">
          <a href="/blog/archives/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-archive"></i> <br />
            
            Archives
          </a>
        </li>
      

      
    </ul>
  

  
</nav>



 </div>
    </header>

    <main id="main" class="main">
      <div class="main-inner">
        <div class="content-wrap">
          <div id="content" class="content">
            

  <div id="posts" class="posts-expand">
    

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="http://yoursite.com/blog/blog/2018/08/06/Distributed/分布式--Lucene-全文检索/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="凌浩雨">
      <meta itemprop="description" content="">
      <meta itemprop="image" content="/blog/images/avatar.jpeg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="凌浩雨_博客">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">分布式--Lucene-全文检索</h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">Posted on</span>
              
              <time title="Post created" itemprop="dateCreated datePublished" datetime="2018-08-06T18:01:38+08:00">
                2018-08-06
              </time>
            

            

            
          </span>

          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        <p>####1. <a href="https://lucene.apache.org/" target="_blank" rel="noopener">Lucene 官网</a></p>
<p>######1). 概述<br>Lucene是一款高性能的、可扩展的信息检索（IR）工具库。信息检索是指文档搜索、文档内信息搜索或者文档相关的元数据搜索等操作。<a href="http://mirrors.hust.edu.cn/apache/lucene/java/7.3.0" target="_blank" rel="noopener">Lucene工具包下载</a></p>
<a id="more"></a>
<p>######2). 索引过程：<br>①获取内容<br>②建立文档<br>获取原始内容后，就需要对这些内容进行索引，必须首先将这些内容转换成部件（通常称为文档），以供搜索引擎使用。文档主要包括几个带值的域，比如标题、正文、摘要、作者和链接。<br>③文档分析<br>搜索引擎不能直接对文本进行索引：确切地说，必须将文本分割成一系列被称为语汇单元的独立的原子元素。每一个语汇单元大致与语言中的“单词”对应起来。<br>④文档索引<br>在索引步骤中，文档被加入到索引列表。</p>
<p>######3). 搜索组件<br>搜索处理过程就是从索引中查找单词，从而找到包含该单词的文档。搜索质量主要由查准率和查全率来衡量。查全率用来衡量搜索系统查找相关文档的能力；而查准率用来衡量搜索系统过滤非相关文档的能力。<br>①用户搜索界面<br>Lucene不提供默认的用户搜索界面，需要自己开发。<br>②建立查询<br>用户从搜索界面提交一个搜索请求，通常以HTML表单或者Ajax请求的形式由浏览器提交到你的搜索引擎服务器。然后将这个请求转换成搜索引擎使用的查询对象格式，这称为建立查询。<br>③搜索查询<br>查询检索索引并返回与查询语句匹配的文档，结果返回时按照查询请求来排序。<br>④展现结果<br>一旦获得匹配查询语句并排好序的文档结果集，接下来就得用直观的、经济的方式为用户展现结果。</p>
<p>######4). 索引过程的核心类<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">IndexWriter </span><br><span class="line">Directory </span><br><span class="line">Analyzer </span><br><span class="line">Document </span><br><span class="line">Field</span><br></pre></td></tr></table></figure></p>
<p>①IndexWriter<br>索引过程的核心组件。这个类负责创建新索引或者打开已有索引，以及向索引中添加、删除或更新被索引文档的信息。可以把IndexWriter看作这样一个对象：它为你提供针对索引文件的写入操作，但不能用于读取或搜索索引。IndexWriter需要开辟一定空间来存储索引，该功能可以由Directory完成。<br>②Directory<br>该类描述了Lucene索引的存放位置。它是一个抽象类，它的子类负责具体指定索引的存储路径。用FSDirectory.open方法来获取真实文件在文件系统的存储路径，然后将它们一次传递给IndexWriter类构造方法。IndexWriter不能直接索引文本，这需要先由Analyzer将文本分割成独立的单词才行。<br>③Analyzer<br>文本文件在被索引之前，需要经过Analyzer（分析器）处理。Analyzer是由IndexWriter的构造方法来指定的，它负责从被索引文本文件中提取语汇单元，并提出剩下的无用信息。如果被索引内容不是纯文本文件，那就需要先将其转换为文本文档。对于要将Lucene集成到应用程序的开发人员来说，选择什么样Analyzer是程序设计中非常关键的一步。分析器的分析对象为文档，该文档包含一些分离的能被索引的域。<br>④Document<br>Document对象代表一些域（Field）的集合。文档的域代表文档或者文档相关的一些元数据。元数据（如作者、标题、主题和修改日期等）都作为文档的不同域单独存储并被索引。Document对象的结构比较简单，为一个包含多个Filed对象容器；Field是指包含能被索引的文本内容的类。<br>⑤Field<br>索引中的每个文档都包含一个或多个不同命名的域，这些域包含在Field类中。每个域都有一个域名和对应的域值，以及一组选项来精确控制Lucene索引操作各个域值。</p>
<p>######5).搜索过程中的核心类<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">IndexSearcher </span><br><span class="line">Term </span><br><span class="line">Query </span><br><span class="line">TermQuery </span><br><span class="line">TopDocs</span><br></pre></td></tr></table></figure></p>
<p>①IndexSearcher<br>该类用于搜索由IndexWriter类创建的索引，它是连接索引的中心环节。可以将IndexSearcher类看作是一个以只读方式打开索引的类。它需要利用Directory实例来掌控前期创建的索引，然后才能提供大量的搜索方法。<br>②Term<br>Term对象是搜索功能的基本单元。Term对象包含一对字符串元素：域名和单词（或域名文本值）。<br>③Query<br>包含了一些非常有用的方法，TermQuery是它的一个子类。<br>④TermQuery<br>该类提供最基本的查询，用来匹配指定域中包含特定项的文档。<br>⑤TopDocs<br>该类是一个简单的指针容器，指针一般指向前N个排名的搜索结果，搜索结果即匹配查询条件的文档。</p>
<p>######6). 域索引选项</p>
<ul>
<li>Index.ANALYZED：使用分析器将值域分解成独立的语汇单元流，并使每个语汇单元能被搜索。该选项使用于普通文本域（如正文、标题、摘要等）。</li>
<li>Index.NOT_ANALYZED：对域进行索引，但不对String值进行分析。该操作实际上将值域作为单一语汇单元并使之能被搜索。该选项适用于索引那些不能被分解的值域，如URL、文件路径、日期、人名、社保号码和电话号码等。该选项尤其适用于“精确匹配”搜索。</li>
<li>Index.ANALYZED_NO_NORMS：不会在索引中存储norms信息。</li>
<li>Index.NOT_ANALYZED_NO_NORMS：不存储norms。用于在搜索期间节省索引空间和减少内存耗费。</li>
</ul>
<p>######7).域存储选项</p>
<ul>
<li>Store.YES：指定存储域值。该情况下，原始的字符串值全部被保存在索引中，并可以由IndexReader类恢复。该选项对于需要展示搜索结果的一些域很有用（如URL、标题或数据库主键）。如果索引的大小在搜索程序考虑之列的话，不要存储太大的域值，因为存储这些域值会消耗掉索引的存储空间。</li>
<li>Store.NO：指定不存储域值。<br>######8). Lucene 并发处理规则<br>任意数量的制度只读的IndexReader类都可以同时打开一个索引。在单个JVM内，利用资源和发挥效率最好的办法是用多线程共享单个的IndexReader实例。<br>对于一个索引来说，一次只能打开一个Writer。lucene采用文件锁来提供保障。一旦建立起IndexWriter对象，系统会分配一个锁，该锁只有当IndexWriter对象被关闭时才会释放。<br>IndexReader 对象甚至可以在IndexWriter对象正在修改索引时打开。每个IndexReader对象将向索引展示自己被打开的时间点。该对象只有在IndexWriter对象提交修改或自己被重新打开后才能获知索引的修改情况。在已经有IndexReader对象被打开的情况下，打开新的IndexReader时采用参数cache=true，这样新的IndexReader会持续检查索引的情况。<br>任何多个线程都可以共享同一个IndexReader类或IndexWriter类。这些类不仅是线程安全的，而且是线程友好的。</li>
</ul>
<p>######9). IndexReader和IndexWriter删除文档的区别 </p>
<ul>
<li>IndexReader能够根据文档号删除文档。Indexwriter不能进行这样的操作，因为文档号可能因为段合并操作而立即产生变化。 </li>
<li>IndexReader 可以通过Term对象删除文档，与IndexWriter类似。但IndexReader会返回被删除的文档号，而IndexWriter不能。IndexReader可以立即决定删除哪个文档，因此就能够对这些文档数量进行计算；而IndexWriter仅仅是将被删除的Term进行缓存，后续在进行实际的删除操作。 </li>
<li>如果程序使用相同的reader进行搜索的话，IndexReader的删除操作会即使生效。IndexWriter的删除操作必须等到程序打开一个新Reader时才能被感知。 </li>
<li>IndexWriter可以通过Query对象执行删除操作，但IndexReader则不行。<br>####2. 子类<br>######1). Directory子类</li>
<li>SimpleFSDirectory<br>最简单的Directory子类，使用java.io.* API将文件存入文件系统，不能很好的支持多线程<br>NIOFSDirectory</li>
<li>使用java.nio.* API 将文件保存至文件系统。能很好支持除Windows之外的多线程操作，原因是Sun的JRE在windows平台上长期存在的问题。</li>
<li>NMapDirectory<br>使用内存映射 I/O进行文件访问。对于64位JRE来说是一个很好选择，对于32位JRE并且索引尺寸相对较小时也可以使用该类</li>
<li>RAMDirectory<br>将所有的文件都存入RAM中，但是不推荐使用于较多索引的情况。会造成资源的浪费，以及因为它使用1024字节大小的内部缓冲器。</li>
<li>FileSwitchDirectory<br>使用两个文件目录，根据文件拓展名在两个目录之间切换使用</li>
</ul>
<p>######2). 核心锁实现</p>
<ul>
<li>NativeFSLockFactory<br>FSDirectory的默认锁，使用java.nio本地操作系统锁，在JVM还存在的情况下不会释放剩余的被锁文件。但该锁可能无法与一些共享文件系统很好地协同，特别是NFS文件系统</li>
<li>SimpleFSLockFactory<br>使用Java的File.createNewFile API,它比NativeFSLockFactory更易于在不同文件系统间移植。</li>
<li>SingleInstanceLockFactory<br>在内存中创建一个完全的锁，该类是RAMDirectory默认的锁实现子类。在程序知道所有IndexWriter将在同一个JVM实例化时使用该类</li>
<li>NoLockFactory<br>完全关闭锁机制。只有在程序确认不需要使用Lucene通畅的锁保护机制时才能使用它。</li>
</ul>
<p>######3).搜索类</p>
<ul>
<li>TermQuery：对索引中特定项进行搜索，查询值区分大小写。</li>
<li>TermRangeQuery：索引中各个Term对象会按照字典排序顺序进行排列，并允许在Lucene的TermRangeQuery对象提供的范围内进行文本项的直接搜索。</li>
<li>NumericRangeQuery：在指定的数字范围内搜索。和TermQuery类一样，newIntRange方法中的两个Boolean参数表示搜索范围是（用true表示）否（用false表示）包含起点和终点。</li>
<li>PrefixQuery：搜索包含以指定字符串开头的项的文档。</li>
<li>BooleanQuery：可以将各种查询类型组合成复杂的查询方式。 <ul>
<li>BooleanClause.Occur.MUST : 只有匹配该查询语句的文档才在考虑之列。  </li>
<li>BooleanClause.Occur.SHOULD: 该项只是可选项。</li>
<li>BooleanClause.Occur.MUST_NOT: 意味着搜索结果不会包含任何匹配该查询子举的文档。默认允许包含1024个查询子句，超过最大值时，程序会抛出TooManyClauses异常。</li>
</ul>
</li>
<li>PhraseQuery：根据位置信息定位某个距离范围内的项所对应的文档。在匹配的情况下，两个项的位置之间所允许的最大间隔距离称为slop，这里的距离是指项若要按顺序组成给定短语锁需要移动位置的次数。</li>
<li>WildcardQuery：使用不完整的、缺少某些字母的项进行查询。*代表0个或者多个字母，？代表0个或者1个字母。</li>
<li>FuzzyQuery：用于匹配与指定项相似的项。</li>
<li>MatchAllDocsQuery：匹配索引中的所有文档。<br>######4). 常用分析器</li>
<li>WhitespaceAnalyzer：通过空格来分割文本信息，而并不对生成的语汇单元进行其他的规范化处理。</li>
<li>SimpleAnalyzer：首先通过非字母字符来分割文本信息，然后将语汇单元统一为小写形式。会去掉数字类型的字符，但会保留其他字符。</li>
<li>StopAnalyzer：会去除英文中的常用单词（如 the、a等）。</li>
<li>StandardAnalyzer：包含大量的逻辑操作来识别某些种类的语汇单元，比如公司名称、E-mail地址以及主机名称等。还会将语汇单元转换为小写形式，并去除停用词和标点符号。<br>######5). 语汇单元属性</li>
<li>TermAttribute：语汇单元对应的文本</li>
<li>PositionIncrementAttribute：位置增量（默认值为1）</li>
<li>OffsetAttriute：起始字符和终止字符的偏移量</li>
<li>TypeAttribute：语汇单元类型（默认为单词）</li>
<li>FlagsAttribute：自定义标志位</li>
<li>PayloadAttribute：每个语汇单元的byte[]类型有效负载<br>######6). 主要可用分析器</li>
<li>WhitespaceAnalyzer：根据空格拆分语汇单元</li>
<li>SimpleAnalyzer：根据非字母字符拆分文本，将其转换为小写形式</li>
<li>StopAnalyzer：根据非字母字符拆分文本，然后小写化，再移除停用词</li>
<li>KeywordAnalyzer：将整个文本作为一个单一语汇单元处理</li>
<li>StandardAnalyzer：基于复杂的语法来生成语汇单元，该语法能识别E-mail地址、首字母缩写词词、韩语/汉语/日语等字符、字母数字等，还能完成小写转换和移除停用词。<br>######7).索引文件格式</li>
<li>数据结构<br>索引包含了存储的文档(document)正排、倒排信息，用于文本搜索。索引又分为多个段（segments），每个新添加的doc都会存到一个新segment中，不同的segments又会合并成一个segment。segment存储着具体的documents，每个doc有一系列的字段组成，一个field的值是多个词（term），一个term是以一些bytes。其递进关系如下：<br>index -&gt; segments -&gt; documents -&gt; fields -&gt; terms</li>
<li>文件格式<ul>
<li>全局文件<ul>
<li>segments_N：记录索引的段数、各段名、各段中文档数、删除数和更新数。可能有多个segments_N文件，最大的N的segments_N是有效文件。</li>
<li>segments.gen：记录当前index的代数（generation），即segments_N的最大N。</li>
<li>write.lock：阻止多给我IndexWriter同时修改索引，一次只能有一个IndexWriter。</li>
</ul>
</li>
<li>段文件<ul>
<li>段描述：<br>xxx.si：段的元数据，如此段的文档及相关文件<br>xxx.del：删除的doc</li>
<li>field信息：<br>xxx.fnm：field names，field名称、索引方式。存储域文件的信息<br>xxx.fdx：field index，索引xxx.fdt。存储域数据的指针<br>xxx.fdt：field data，存储stored fields</li>
<li>term信息<br>xxx.tip：term index，xxx.tim的索引，实现对xxx.tim的随机存取<br>xxx.tim：term directory，按字典顺序排列的terms，其值指向.doc/.pos<br>xxx.doc：倒排列表，term所在的docs、在doc中的频率<br>xxx.pos：倒排列表，term在doc中的位置<br>xxx.pay：payloads and offsets，term在doc中的offset</li>
<li>term vector<br>term vector 用于打分，存储StoreTermVectors的field<br>xxx.tvx：term vector index，每个doc 在xxx.tvd、xxx.tvf中的位置<br>xxx.tvd：term vector data file，每个doc的term vector field信息在xxx.tvf中的位置<br>xxx.tvf：term vector fields，field的term列表及各term的频率、位置或者偏移</li>
<li>归一化<br>xxx.nvm：norms metadata<br>xxx.nvd：norms data</li>
<li>doc values<br>xxx.dvm：DocValues metadata<br>xxx.dvd：DocValues data</li>
<li>复合文件<br>xxx.cfs,xxx.cfe：复合索引的文件，在系统上虚拟的一个文件，用于频繁的文件句柄</li>
<li>词频文件<br>xxx.frq：词频文件，包含文档列表以及每一个term和其词频</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>####3. Luence 使用</p>
<p>######1). 全文检索过程<br><img src="https://upload-images.jianshu.io/upload_images/3110861-affc14faa0cff776.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="图1.png"></p>
<p>######2). 创建文档对象<br>获取原始内容的目的是为了索引,在索引前,需要将原始内容创建成文档(Document),文档中包括一个一个的域(Field),域中存储内容;我们可以将磁盘上的一个文件当成一个 document, Document 中包括一些Field(file_name 文件名称, file_path文件路径, file_size 文件大小, file_content 文件内容);一个 Document 可以有多个 Field,同一个Document,可以有相同的 Field(域名和域值都相同);每一个 Document 都有一个唯一的编号,就是文档 id;<br><img src="https://upload-images.jianshu.io/upload_images/3110861-40a5c018bcc2b685.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="图2.png"></p>
<p>######3). 分析文档<br>将原始内容创建为包含域(Field)的文档(document),需要再对域中的内容进行分析,分析的过程是经过对原始文档提取单词,将字母转为小写,去除标点符号,去除停用词等过程生成最终的语汇单元,可以将语汇单元理解为一个一个的单词;每一个单词叫做一个Term,不同的域中拆分出来的相同的单词是不同的term; term中包含两部分,一部分是文档的域名, 另一部分是单词的内容。</p>
<p><strong>Field 域的属性</strong></p>
<ul>
<li>是否分析: 是否对域的内容进行分词处理;</li>
<li>是否索引: 将 Field 分析后的词或整个 Field 值进行索引,只有建立索引,才能搜索到;</li>
<li>是否存储: 存储在文档中的 Field 才可以从 Document 中获取;<br><img src="https://upload-images.jianshu.io/upload_images/3110861-7a31faf9b6ba9ccb.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="图3.png"></li>
</ul>
<p>######4). 创建索引<br>对所有文档分析得出的语汇单元进行索引,索引的目的是为了搜索,最终要实现只搜索被索引的语汇单元从而找到 Document，这种索引的结构叫倒排索引结构;传统方法是根据文件找到该文件的内容,在文件内容中匹配搜索关键字,这种方法是顺序扫描方法,数据量大,搜索慢;倒排索引结构是根据内容(词语)找文档; 顺序扫描方法是根据文档查找里面的内容。<br><img src="https://upload-images.jianshu.io/upload_images/3110861-5151fba2715c4c67.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="图4.png"></p>
<p>I. 导入jar包<br>commons-io-2.5.jar、lucene-analyzers-common-7.3.0.jar、lucene-core-7.3.0.jar、lucene-queryparser-7.3.0.jar<br><img src="https://upload-images.jianshu.io/upload_images/3110861-5c44a19d532b9c7f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="图5.png"></p>
<p>II. 测试代码<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br></pre></td><td class="code"><pre><span class="line">/**</span><br><span class="line"> *  Lucene索引 测试</span><br><span class="line"> * 使用到的Jar包：</span><br><span class="line"> * commons-io-2.5.jar</span><br><span class="line"> * lucene-analyzers-common-7.3.0.jar</span><br><span class="line"> * lucene-core-7.3.0.jar</span><br><span class="line"> * lucene-queryparser-7.3.0.jar</span><br><span class="line"> * </span><br><span class="line"> * @author mazaiting</span><br><span class="line"> */</span><br><span class="line">public class IndexTest &#123;</span><br><span class="line">	</span><br><span class="line">	/**</span><br><span class="line">	 * 测试创建索引</span><br><span class="line">	 * @throws IOException</span><br><span class="line">	 */</span><br><span class="line">	@Test</span><br><span class="line">	public void createIndexTest() throws IOException &#123;</span><br><span class="line">		// 指定索引库的存放位置(Directory 对象)</span><br><span class="line">		Path path = FileSystems.getDefault().getPath(&quot;D:\\distribution\\lucene&quot;);</span><br><span class="line">		// 1. 创建Directory对象</span><br><span class="line">		// FSDirectory磁盘存储; Directory 保存索引</span><br><span class="line">		Directory directory = FSDirectory.open(path);</span><br><span class="line">		// 2. 指定分词器</span><br><span class="line">		// 基于复杂的语法来生成语汇单元，该语法能识别E-mail地址、首字母缩写词词、</span><br><span class="line">		// 韩语/汉语/日语等字符、字母数字等，还能完成小写转换和移除停用词</span><br><span class="line">		Analyzer analyzer = new StandardAnalyzer();</span><br><span class="line">		// IndexWriter配置对象</span><br><span class="line">		IndexWriterConfig config = new IndexWriterConfig(analyzer);</span><br><span class="line">		// 3. 创建IndexWriter对象</span><br><span class="line">		IndexWriter indexWriter = new IndexWriter(directory, config);</span><br><span class="line">		</span><br><span class="line">		// 4. 指定原始文件的目录</span><br><span class="line">		File fileDir = new File(&quot;G:\\test&quot;);</span><br><span class="line">		// 获取文件夹和文件列表</span><br><span class="line">		File[] fileList = fileDir.listFiles();</span><br><span class="line">		</span><br><span class="line">		// 遍历</span><br><span class="line">		for (File file : fileList) &#123;</span><br><span class="line">			// 判断是否为路径，如果不是路径则执行里面的内容</span><br><span class="line">			if (!file.isDirectory()) &#123;</span><br><span class="line">				// 5. 创建文档对象</span><br><span class="line">				Document document = new Document();</span><br><span class="line">				</span><br><span class="line">				// 文件名称</span><br><span class="line">				// 分词 索引 存储</span><br><span class="line">				String fileName = file.getName();</span><br><span class="line">				Field fileNameField = new TextField(&quot;fileName&quot;, fileName, Store.YES);</span><br><span class="line">				</span><br><span class="line">				// 文件大小</span><br><span class="line">				// 分词 索引 存储</span><br><span class="line">				long fileSize = FileUtils.sizeOf(file);</span><br><span class="line">				Field fileSizeField = new TextField(&quot;fileSize&quot;, String.valueOf(fileSize), Store.YES);</span><br><span class="line">				</span><br><span class="line">				// 文件路径</span><br><span class="line">				// 不分词 不索引 存储</span><br><span class="line">				String filePath = file.getPath();</span><br><span class="line">				Field filePathField = new StoredField(&quot;filePath&quot;, filePath);</span><br><span class="line">				</span><br><span class="line">				// 文件内容</span><br><span class="line">				String fileContent = FileUtils.readFileToString(file, &quot;UTF-8&quot;);</span><br><span class="line">				Field fileContentField = new TextField(&quot;fileContent&quot;, fileContent, Store.YES);</span><br><span class="line">						</span><br><span class="line">				// 添加字段</span><br><span class="line">				document.add(fileNameField);</span><br><span class="line">				document.add(fileSizeField);</span><br><span class="line">				document.add(filePathField);</span><br><span class="line">				document.add(fileContentField);</span><br><span class="line">				</span><br><span class="line">				// 使用IndexWriter对象将Document对象写入到索引库</span><br><span class="line">				indexWriter.addDocument(document);</span><br><span class="line">			&#125;</span><br><span class="line">		&#125;</span><br><span class="line">		// 关闭IndexWriter对象</span><br><span class="line">		indexWriter.close();</span><br><span class="line">	&#125;	</span><br><span class="line">	</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>III. 执行测试代码<br><code>G:\\test</code>目录文件如下：<br><img src="https://upload-images.jianshu.io/upload_images/3110861-7861af3a89460de4.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="图6.png"></p>
<p>在路径<code>D:\distribution\lucene\</code>多了些文件</p>
<p><img src="https://upload-images.jianshu.io/upload_images/3110861-4a979331ce0be062.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="图7.png"></p>
<p>######5). 查询索引<br>用户输入查询关键字执行搜索前,需要先创建一个查询对象,查询对象中可以指定查询要搜索的 Field 文档域,查询关键字等,查询对象会生成具体的查询语法;根据查询语法在倒排索引词典表中分别找出对应搜索词的索引,从而找到索引所链接的文档链表。<br><img src="https://upload-images.jianshu.io/upload_images/3110861-b0b3fdd6c7b6d1ba.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="图7.png"></p>
<p>I. 测试代码<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br></pre></td><td class="code"><pre><span class="line">/**</span><br><span class="line"> * Lucene索引 测试</span><br><span class="line"> * 使用到的Jar包：</span><br><span class="line"> * commons-io-2.5.jar</span><br><span class="line"> * lucene-analyzers-common-7.3.0.jar</span><br><span class="line"> * lucene-core-7.3.0.jar</span><br><span class="line"> * lucene-queryparser-7.3.0.jar</span><br><span class="line"> * </span><br><span class="line"> * @author mazaiting</span><br><span class="line"> */</span><br><span class="line">public class IndexTest &#123;</span><br><span class="line">	/**</span><br><span class="line">	 * 查询索引</span><br><span class="line">	 * 步骤：</span><br><span class="line">	 * 	1. 创建一个Directory对象，用于指定索引库存放的位置</span><br><span class="line">	 * 	2. 创建一个IndexReader对象，需要指定Directory对象，用于读取索引库中的文件</span><br><span class="line">	 *  3. 创建一个IndexSearcher对象，需要指定IndexReader对象</span><br><span class="line">	 *  4. 创建一个TermQuery对象，指定查询的域和查询的关键词</span><br><span class="line">	 *  5. 执行查询</span><br><span class="line">	 *  6. 返回查询结果，遍历查询结果并输出</span><br><span class="line">	 *  7. 关闭IndexReader	</span><br><span class="line">	 * @throws IOException </span><br><span class="line">	 */</span><br><span class="line">	@Test</span><br><span class="line">	public void searchIndexTest() throws IOException &#123;</span><br><span class="line">		// Directory, 指定索引库存放的位置</span><br><span class="line">		Path path = FileSystems.getDefault().getPath(&quot;D:\\distribution\\lucene&quot;);</span><br><span class="line">		Directory directory = FSDirectory.open(path);</span><br><span class="line">		// IndexReader, 读取索引库中的文件</span><br><span class="line">		IndexReader indexReader = DirectoryReader.open(directory);</span><br><span class="line">		// IndexSearcher, 用于查询</span><br><span class="line">		IndexSearcher indexSearcher = new IndexSearcher(indexReader);</span><br><span class="line">		// TermQuery, 指定查询的域和查询的关键词</span><br><span class="line">		Query query = new TermQuery(new Term(&quot;fileName&quot;, &quot;java.txt&quot;));</span><br><span class="line">		// 执行查询</span><br><span class="line">		TopDocs topDocs = indexSearcher.search(query, 100);</span><br><span class="line">		// 获取数组</span><br><span class="line">		ScoreDoc[] scoreDocs =  topDocs.scoreDocs;</span><br><span class="line">		System.out.println(scoreDocs.length);</span><br><span class="line">		// 遍历结果文档</span><br><span class="line">		for (ScoreDoc scoreDoc : scoreDocs) &#123;</span><br><span class="line">			// 获取文档id</span><br><span class="line">			int docId = scoreDoc.doc;</span><br><span class="line">			// 通过id从索引中获取对应的文档</span><br><span class="line">			Document document = indexReader.document(docId);</span><br><span class="line">			// 获取文件名称</span><br><span class="line">			String fileName = document.get(&quot;fileName&quot;);</span><br><span class="line">			// 获取文件路径</span><br><span class="line">			String filePath = document.get(&quot;filePath&quot;);</span><br><span class="line">			// 获取文件大小</span><br><span class="line">			String fileSize = document.get(&quot;fileSize&quot;);</span><br><span class="line">			// 获取文件内容</span><br><span class="line">			String fileContent = document.get(&quot;fileContent&quot;);</span><br><span class="line">			System.out.println(&quot;==========================================&quot;);</span><br><span class="line">			System.out.println(&quot;文件名：&quot; + fileName + &quot;\n&quot;</span><br><span class="line">					+ &quot;文件大小： &quot; + fileSize + &quot;\n&quot;</span><br><span class="line">					+ &quot;文件路径：&quot; + filePath + &quot;\n&quot;</span><br><span class="line">					+ &quot;文件内容：&quot; + fileContent);</span><br><span class="line">			</span><br><span class="line">		&#125;</span><br><span class="line">		// 关闭IndexReader</span><br><span class="line">		indexReader.close();</span><br><span class="line">	&#125;</span><br><span class="line">	</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>II. 执行测试代码<br>打印结果:<br><img src="https://upload-images.jianshu.io/upload_images/3110861-d31d1f7b1da8e908.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="图8.png"></p>
<p>######6). 分词器<br><strong>支持中文的分词器： IKAnalyzer</strong><br>从一个 Reader 字符流开始,创建一个基于 Reader 的 Tokenizer分词器,经过三个 TokenFilter,生成语汇单元 Tokens。<br><img src="https://upload-images.jianshu.io/upload_images/3110861-29d4776cfd2b9fc1.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="图9.png"><br>I. 代码<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br></pre></td><td class="code"><pre><span class="line">/**</span><br><span class="line"> * Lucene索引 测试</span><br><span class="line"> * 使用到的Jar包：</span><br><span class="line"> * commons-io-2.5.jar</span><br><span class="line"> * lucene-analyzers-common-7.3.0.jar</span><br><span class="line"> * lucene-core-7.3.0.jar</span><br><span class="line"> * lucene-queryparser-7.3.0.jar</span><br><span class="line"> * </span><br><span class="line"> * @author mazaiting</span><br><span class="line"> */</span><br><span class="line">public class IndexTest &#123;</span><br><span class="line">	</span><br><span class="line">	/**</span><br><span class="line">	 * 查看标准分词器的分词效果</span><br><span class="line">	 * @throws IOException </span><br><span class="line">	 */</span><br><span class="line">	@Test</span><br><span class="line">	public void analyzerTest() throws IOException &#123;</span><br><span class="line">		// 创建一个标准分词器对象</span><br><span class="line">		Analyzer analyzer = new StandardAnalyzer();</span><br><span class="line">		// 获得TokenStream对象</span><br><span class="line">		// 参数1： 字段名，可以随便给；参数2: 要分析的文本内容</span><br><span class="line">		TokenStream tokenStream = analyzer.tokenStream(&quot;test&quot;, </span><br><span class="line">				&quot;The Spring Framework provides a comprehensive programming and configuration model.&quot;);</span><br><span class="line">		// 添加引用，可以获得每个关键字</span><br><span class="line">		CharTermAttribute charTermAttribute = tokenStream.addAttribute(CharTermAttribute.class);</span><br><span class="line">		// 添加一个偏移量的引用，记录了关键词的开始位置及结束位置</span><br><span class="line">		OffsetAttribute offsetAttribute = tokenStream.addAttribute(OffsetAttribute.class);</span><br><span class="line">		// 将指针调整到列表的头部</span><br><span class="line">		tokenStream.reset();</span><br><span class="line">		// 遍历关键词列表，通过incrementToken方法判断列表是否结束</span><br><span class="line">		while (tokenStream.incrementToken()) &#123;</span><br><span class="line">			// 关键词其实位置</span><br><span class="line">			System.out.println(&quot;start-&gt;&quot; + offsetAttribute.startOffset());</span><br><span class="line">			// 取关键词</span><br><span class="line">			System.out.println(charTermAttribute);</span><br><span class="line">			// 结束位置</span><br><span class="line">			System.out.println(&quot;end-&gt;&quot; + offsetAttribute.endOffset());			</span><br><span class="line">		&#125;</span><br><span class="line">		// 关闭</span><br><span class="line">		tokenStream.close();</span><br><span class="line">		analyzer.close();</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>II. 执行测试<br><img src="https://upload-images.jianshu.io/upload_images/3110861-23458cf9cec8b683.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="图10.png"></p>
<p>######7). 索引库维护工具类<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br></pre></td><td class="code"><pre><span class="line">/**</span><br><span class="line"> * 索引库维护工具类</span><br><span class="line"> * @author mazaiting</span><br><span class="line"> */</span><br><span class="line">public class LuceneManager &#123;</span><br><span class="line">	/**</span><br><span class="line">	 * 获取IndexWriter对象</span><br><span class="line">	 * @return</span><br><span class="line">	 */</span><br><span class="line">	public IndexWriter getIndexWriter() &#123;</span><br><span class="line">		try &#123;</span><br><span class="line">			// 获取索引库路径</span><br><span class="line">			Path path = FileSystems.getDefault().getPath(&quot;D:\\distribution\\lucene&quot;);</span><br><span class="line">			// 创建索引库字典</span><br><span class="line">			Directory directory = FSDirectory.open(path);</span><br><span class="line">			// 创建分析器</span><br><span class="line">			Analyzer analyzer = new StandardAnalyzer();</span><br><span class="line">			// 创建IndexWriter配置</span><br><span class="line">			IndexWriterConfig config = new IndexWriterConfig(analyzer);</span><br><span class="line">			return new IndexWriter(directory, config);</span><br><span class="line">		&#125; catch (IOException e) &#123;</span><br><span class="line">			e.printStackTrace();</span><br><span class="line">		&#125;</span><br><span class="line">		return null;</span><br><span class="line">	&#125;</span><br><span class="line">	</span><br><span class="line">	/**</span><br><span class="line">	 * 全部删除 </span><br><span class="line">	 * @throws IOException</span><br><span class="line">	 */</span><br><span class="line">	@Test</span><br><span class="line">	public void delAllTest() throws IOException &#123;</span><br><span class="line">		IndexWriter writer = getIndexWriter();</span><br><span class="line">		writer.deleteAll();</span><br><span class="line">		writer.close();</span><br><span class="line">	&#125;</span><br><span class="line">	</span><br><span class="line">	/**</span><br><span class="line">	 * 根据条件删除</span><br><span class="line">	 * @throws IOException </span><br><span class="line">	 */</span><br><span class="line">	@Test</span><br><span class="line">	public void delTest() throws IOException &#123;</span><br><span class="line">		IndexWriter writer = getIndexWriter();</span><br><span class="line">		Query query = new TermQuery(new Term(&quot;fileName&quot;, &quot;java&quot;));</span><br><span class="line">		writer.deleteDocuments(query);</span><br><span class="line">		writer.close();</span><br><span class="line">	&#125;</span><br><span class="line">	</span><br><span class="line">	/**</span><br><span class="line">	 * 更新</span><br><span class="line">	 * @throws IOException </span><br><span class="line">	 */</span><br><span class="line">	@Test</span><br><span class="line">	public void update() throws IOException &#123;</span><br><span class="line">		IndexWriter writer = getIndexWriter();</span><br><span class="line">		Document document = new Document();</span><br><span class="line">		document.add(new TextField(&quot;fileName&quot;, &quot;测试文件名&quot;, Store.YES));</span><br><span class="line">		document.add(new TextField(&quot;fileContent&quot;, &quot;测试文件内容&quot;, Store.YES));</span><br><span class="line">		</span><br><span class="line">		// 将lucene删除， 然后添加</span><br><span class="line">		writer.updateDocument(new Term(&quot;fileName&quot;, &quot;lucene&quot;), document);</span><br><span class="line">		writer.close();</span><br><span class="line">	&#125;</span><br><span class="line">	</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>######8). 索引库查询<br>对要搜索的信息创建 Query 查询对象,Lucene会根据 Query 查询对象生成最终的查询语法;<br>可通过两种方法创建查询对象:</p>
<ul>
<li>使用 Lucene 提供的 Query子类;</li>
<li>使用 QueryParse 解析查询表达式, 需要加入lucene-queryparser-7.3.0.jar<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br></pre></td><td class="code"><pre><span class="line">/**</span><br><span class="line"> * 索引库维护工具类</span><br><span class="line"> * </span><br><span class="line"> * @author mazaiting</span><br><span class="line"> */</span><br><span class="line">public class LuceneManager &#123;</span><br><span class="line">	/**</span><br><span class="line">	 * 获取IndexSearcher</span><br><span class="line">	 * </span><br><span class="line">	 * @return</span><br><span class="line">	 */</span><br><span class="line">	public IndexSearcher getIndexSearcher() &#123;</span><br><span class="line">		try &#123;</span><br><span class="line">			// 获取索引库路径</span><br><span class="line">			Path path = FileSystems.getDefault().getPath(&quot;D:\\distribution\\lucene&quot;);</span><br><span class="line">			// 创建索引库字典</span><br><span class="line">			Directory directory = FSDirectory.open(path);</span><br><span class="line">			// 创建索引读取者</span><br><span class="line">			IndexReader indexReader = DirectoryReader.open(directory);</span><br><span class="line">			return new IndexSearcher(indexReader);</span><br><span class="line">		&#125; catch (IOException e) &#123;</span><br><span class="line">			e.printStackTrace();</span><br><span class="line">		&#125;</span><br><span class="line">		return null;</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	/**</span><br><span class="line">	 * 获取执行结果</span><br><span class="line">	 * </span><br><span class="line">	 * @throws IOException</span><br><span class="line">	 */</span><br><span class="line">	public void printResult(IndexSearcher indexSearcher, Query query) throws IOException &#123;</span><br><span class="line">		// 执行查询</span><br><span class="line">		TopDocs topDocs = indexSearcher.search(new TermQuery(new Term(&quot;fileName&quot;)), 10);</span><br><span class="line">		// 获取数组</span><br><span class="line">		ScoreDoc[] scoreDocs = topDocs.scoreDocs;</span><br><span class="line">		System.out.println(scoreDocs.length);</span><br><span class="line">		// 遍历结果文档</span><br><span class="line">		for (ScoreDoc scoreDoc : scoreDocs) &#123;</span><br><span class="line">			// 获取文档id</span><br><span class="line">			int docId = scoreDoc.doc;</span><br><span class="line">			// 通过id从索引中获取对应的文档</span><br><span class="line">			Document document = indexSearcher.doc(docId);</span><br><span class="line">			// 获取文件名称</span><br><span class="line">			String fileName = document.get(&quot;fileName&quot;);</span><br><span class="line">			// 获取文件路径</span><br><span class="line">			String filePath = document.get(&quot;filePath&quot;);</span><br><span class="line">			// 获取文件大小</span><br><span class="line">			String fileSize = document.get(&quot;fileSize&quot;);</span><br><span class="line">			// 获取文件内容</span><br><span class="line">			String fileContent = document.get(&quot;fileContent&quot;);</span><br><span class="line">			System.out.println(&quot;==========================================&quot;);</span><br><span class="line">			System.out.println(&quot;文件名：&quot; + fileName + &quot;\n&quot; + &quot;文件大小： &quot; + fileSize + &quot;\n&quot; + &quot;文件路径：&quot; + filePath + &quot;\n&quot;</span><br><span class="line">					+ &quot;文件内容：&quot; + fileContent);</span><br><span class="line"></span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line">	</span><br><span class="line">	/**</span><br><span class="line">	 * 查询所有</span><br><span class="line">	 * @throws IOException </span><br><span class="line">	 */</span><br><span class="line">	@Test</span><br><span class="line">	public void matchAllDocsQueryTest() throws IOException &#123;</span><br><span class="line">		// 获取查询索引对象</span><br><span class="line">		IndexSearcher indexSearcher = getIndexSearcher();</span><br><span class="line">		// 查询所有</span><br><span class="line">		Query query = new MatchAllDocsQuery();</span><br><span class="line">		// 打印结果</span><br><span class="line">		printResult(indexSearcher, query);</span><br><span class="line">		// 关闭资源</span><br><span class="line">		indexSearcher.getIndexReader().close();</span><br><span class="line">	&#125;</span><br><span class="line">	</span><br><span class="line">	/**</span><br><span class="line">	 * 组合查询</span><br><span class="line">	 * @throws IOException </span><br><span class="line">	 */</span><br><span class="line">	@Test</span><br><span class="line">	public void boolQueryTest() throws IOException &#123;</span><br><span class="line">		// 创建搜索</span><br><span class="line">		IndexSearcher indexSearcher = getIndexSearcher();</span><br><span class="line">		// 创建查询</span><br><span class="line">		Query query1 = new TermQuery(new Term(&quot;fileName&quot;, &quot;java.txt&quot;));</span><br><span class="line">		Query query2 = new TermQuery(new Term(&quot;fileName&quot;, &quot;c.txt&quot;));</span><br><span class="line">		// 构建表达式 </span><br><span class="line">		// Occur.MUST: 必须满足此条件, 相当于 and</span><br><span class="line">        // Occur.SHOULD: 应该满足此条件, 但是不满足也可以, 相当于 or</span><br><span class="line">        // Occur.MUST_NOT: 必须不满足, 相当于 not</span><br><span class="line">		BooleanClause clause1 = new BooleanClause(query1, Occur.SHOULD);</span><br><span class="line">		// Build模式创建</span><br><span class="line">		BooleanQuery.Builder builder = new BooleanQuery.Builder();</span><br><span class="line">		// 添加表达式</span><br><span class="line">		builder.add(clause1);</span><br><span class="line">		// 添加查询</span><br><span class="line">		builder.add(query2, Occur.SHOULD);</span><br><span class="line">		// 打印</span><br><span class="line">		printResult(indexSearcher, builder.build());</span><br><span class="line">		// 关闭资源</span><br><span class="line">		indexSearcher.getIndexReader().close();</span><br><span class="line">	&#125;</span><br><span class="line">	</span><br><span class="line">	/**</span><br><span class="line">	 * 使用QueryParser解析查询表达式</span><br><span class="line">	 * @throws ParseException </span><br><span class="line">	 * @throws IOException </span><br><span class="line">	 */</span><br><span class="line">	@Test</span><br><span class="line">	public void queryParserTest() throws ParseException, IOException &#123;</span><br><span class="line">		IndexSearcher indexSearcher = getIndexSearcher();</span><br><span class="line">		// 创建QueryParser对象，其中参数一：字段名，参数而分词器</span><br><span class="line">		QueryParser queryParser = new QueryParser(&quot;fileName&quot;, new StandardAnalyzer());</span><br><span class="line">		// 此时：表示使用默认域：fileName</span><br><span class="line">		// 查询fileContent域</span><br><span class="line">		Query query = queryParser.parse(&quot;fileContent:apache&quot;);</span><br><span class="line">		// 打印</span><br><span class="line">		printResult(indexSearcher, query);</span><br><span class="line">		// 关闭资源</span><br><span class="line">		indexSearcher.getIndexReader().close();</span><br><span class="line">	&#125;</span><br><span class="line">	</span><br><span class="line">	/**</span><br><span class="line">	 * 指定多个默认搜索域</span><br><span class="line">	 * @throws ParseException </span><br><span class="line">	 * @throws IOException </span><br><span class="line">	 */</span><br><span class="line">	@Test</span><br><span class="line">	public void multiFieldQueryParser() throws ParseException, IOException &#123;</span><br><span class="line">		IndexSearcher indexSearcher = getIndexSearcher();</span><br><span class="line">		// 指定多个默认搜索域</span><br><span class="line">		String[] fields = &#123;&quot;fileName&quot;, &quot;fileContent&quot;&#125;;</span><br><span class="line">		// 创建MultiFieldQueryParser对象</span><br><span class="line">		MultiFieldQueryParser queryParser = new MultiFieldQueryParser(fields, new StandardAnalyzer());</span><br><span class="line">		// 创建查询</span><br><span class="line">		Query query = queryParser.parse(&quot;apache&quot;);</span><br><span class="line">		// 输出查询条件</span><br><span class="line">		System.out.println(query);</span><br><span class="line">		// 执行查询</span><br><span class="line">		printResult(indexSearcher, query);</span><br><span class="line">		// 关闭资源</span><br><span class="line">		indexSearcher.getIndexReader().close();</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
</ul>
<p>####<a href="https://gitee.com/mazaiting/distributed" target="_blank" rel="noopener">代码下载</a></p>

      
    </div>
    
    
    

    

    

    

    <footer class="post-footer">
      

      
      
      

      
        <div class="post-nav">
          <div class="post-nav-next post-nav-item">
            
              <a href="/blog/2018/08/06/Distributed/分布式--Linux-基础/" rel="next" title="分布式--Linux-基础">
                <i class="fa fa-chevron-left"></i> 分布式--Linux-基础
              </a>
            
          </div>

          <span class="post-nav-divider"></span>

          <div class="post-nav-prev post-nav-item">
            
              <a href="/blog/2018/08/06/Distributed/分布式--Nginx-负载均衡服务器/" rel="prev" title="分布式--Nginx-负载均衡服务器">
                分布式--Nginx-负载均衡服务器 <i class="fa fa-chevron-right"></i>
              </a>
            
          </div>
        </div>
      

      
      
    </footer>
  </div>
  
  
  
  </article>



    <div class="post-spread">
      
    </div>
  </div>


          </div>
          


          

  



        </div>
        
          
  
  <div class="sidebar-toggle">
    <div class="sidebar-toggle-line-wrap">
      <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
    </div>
  </div>

  <aside id="sidebar" class="sidebar">
    
    <div class="sidebar-inner">

      

      

      <section class="site-overview-wrap sidebar-panel sidebar-panel-active">
        <div class="site-overview">
          <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
            
              <img class="site-author-image" itemprop="image"
                src="/blog/images/avatar.jpeg"
                alt="凌浩雨" />
            
              <p class="site-author-name" itemprop="name">凌浩雨</p>
              <p class="site-description motion-element" itemprop="description">专业从事于移动端开发，Android与iOS均有涉及，主做Android开发与React Native开发</p>
          </div>

          <nav class="site-state motion-element">

            
              <div class="site-state-item site-state-posts">
              
                <a href="/blog/archives/">
              
                  <span class="site-state-item-count">393</span>
                  <span class="site-state-item-name">posts</span>
                </a>
              </div>
            

            

            

          </nav>

          

          

          
          

          
          

          

        </div>
      </section>

      

      

    </div>
  </aside>


        
      </div>
    </main>

    <footer id="footer" class="footer">
      <div class="footer-inner">
        <div class="copyright">&copy; <span itemprop="copyrightYear">2018</span>
  <span class="with-love">
    <i class="fa fa-user"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">凌浩雨</span>

  
</div>


  <div class="powered-by">Powered by <a class="theme-link" target="_blank" href="https://hexo.io">Hexo</a></div>



  <span class="post-meta-divider">|</span>



  <div class="theme-info">Theme &mdash; <a class="theme-link" target="_blank" href="https://github.com/iissnan/hexo-theme-next">NexT.Pisces</a> v5.1.4</div>




        







        
      </div>
    </footer>

    
      <div class="back-to-top">
        <i class="fa fa-arrow-up"></i>
        
      </div>
    

    

  </div>

  

<script type="text/javascript">
  if (Object.prototype.toString.call(window.Promise) !== '[object Function]') {
    window.Promise = null;
  }
</script>









  












  
  
    <script type="text/javascript" src="/blog/lib/jquery/index.js?v=2.1.3"></script>
  

  
  
    <script type="text/javascript" src="/blog/lib/fastclick/lib/fastclick.min.js?v=1.0.6"></script>
  

  
  
    <script type="text/javascript" src="/blog/lib/jquery_lazyload/jquery.lazyload.js?v=1.9.7"></script>
  

  
  
    <script type="text/javascript" src="/blog/lib/velocity/velocity.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/blog/lib/velocity/velocity.ui.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/blog/lib/fancybox/source/jquery.fancybox.pack.js?v=2.1.5"></script>
  


  


  <script type="text/javascript" src="/blog/js/src/utils.js?v=5.1.4"></script>

  <script type="text/javascript" src="/blog/js/src/motion.js?v=5.1.4"></script>



  
  


  <script type="text/javascript" src="/blog/js/src/affix.js?v=5.1.4"></script>

  <script type="text/javascript" src="/blog/js/src/schemes/pisces.js?v=5.1.4"></script>



  
  <script type="text/javascript" src="/blog/js/src/scrollspy.js?v=5.1.4"></script>
<script type="text/javascript" src="/blog/js/src/post-details.js?v=5.1.4"></script>



  


  <script type="text/javascript" src="/blog/js/src/bootstrap.js?v=5.1.4"></script>



  


  




	





  





  












  





  

  

  

  
  

  

  

  

</body>
</html>
